import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ContractCommand from './contractCommand';
import {toWidget, viewToModelPositionOutsideModelElement} from '@ckeditor/ckeditor5-widget/src/utils';
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
import '../../theme/contract.css';

export default class ContractEditing extends Plugin {
    static get requires() {
        return [Widget];
    }

    init() {
        console.log('PlaceholderEditing#init() got called');

        this._defineSchema();
        this._defineConverters();

        this.editor.commands.add('contract', new ContractCommand(this.editor));

        this.editor.editing.mapper.on(
            'viewToModelPosition',
            viewToModelPositionOutsideModelElement(this.editor.model, viewElement => viewElement.hasClass('ck-contract'))
        );
        // this.editor.config.define('placeholderConfig', {
        //     types: ['date', 'first name', 'surname']
        // });
    }

    _defineSchema() {
        const schema = this.editor.model.schema;

        schema.register('contract', {
            // Allow wherever text is allowed:
            allowWhere: '$text',

            // The placeholder will act as an inline node:
            isInline: true,

            // The inline widget is self-contained so it cannot be split by the caret and it can be selected:
            isObject: true,

            // The placeholder can have many types, like date, name, surname, etc:
            allowAttributes: ['name']
        });
    }

    _defineConverters() {
        const conversion = this.editor.conversion;

        conversion.for('upcast').elementToElement({
            view: {
                name: 'span',
                classes: ['contract']
            },
            model: (viewElement, {writer: modelWriter}) => {
                // Extract the "name" from "{name}".
                const name = viewElement.getChild(0).data.slice(1, -1);

                return modelWriter.createElement('contract', {name});
            }
        });

        conversion.for('editingDowncast').elementToElement({
            model: 'contract',
            view: (modelItem, viewWriter) => {
                const widgetElement = createPlaceholderView(modelItem, viewWriter);

                // Enable widget handling on a placeholder element inside the editing view.
                return toWidget(widgetElement, viewWriter);
            }
        });

        conversion.for('dataDowncast').elementToElement({
            model: 'contract',
            view: (modelItem, viewWriter) => createPlaceholderView(modelItem, viewWriter)
        });

        // Helper method for both downcast converters.
        function createPlaceholderView(modelItem, viewWriter) {
            const name = modelItem.getAttribute('name');
            const placeholderView = viewWriter.createContainerElement('span', {
                class: 'ck-contract'
            });

            // Insert the placeholder name (as a text).
            const innerText = viewWriter.createText('{#' + name + '#}');
            viewWriter.insert(viewWriter.createPositionAt(placeholderView, 0), innerText);

            return placeholderView;
        }
    }
}